perm filename CONCEP.1[CLS,LSP] blob
sn#825853 filedate 1986-10-27 generic text, type T, neo UTF8
\input macros
\def\bookline{\CLOS\ Specification}
\def\chapline{Basic User Interface Concepts}
\beginChapter 1.{Common Lisp Object System Specification}%
{Basic User Interface Concepts}{Basic User Interface Concepts}
Contributors to this document include Daniel G. Bobrow, Linda G.
DeMichiel,\break Richard P. Gabriel, Kenneth Kahn, Sonya E. Keene,
Gregor Kiczales, Larry\break Masinter, David A. Moon, Mark Stefik, and
Daniel L. Weinreb.
Comments and suggestions on this document are encouraged.
Changes will be incorporated over the next several months.
This text will be made available to the X3J13 Committee for the
Common Lisp Standards effort.
\endTitlePage
\beginSection{Introduction}
This chapter describes the standard user interface for object-oriented
programming in the \CLOS. The chapter ``Meta-Object
Protocol'' describes how the \CLOS\ can be customized to accommodate
existing object-oriented paradigms and to define new ones.
\vfill
\endSection%{Introduction}
\beginSection{Objects and Classes}
Under this proposal, the primitive entities of Common Lisp are called
{\bit objects}. Every Common Lisp data structure is an object that
is an {\bit instance\/} of a unique class.
A {\bit class\/} determines the structure and behavior of a set of
objects, called its {\bit instances}. The class of an object
indirectly determines the set of operations into which the object can
enter. It is an important feature of the \OS\ that all Lisp data
structures have a determinable class.
A class is itself an object.
Like other objects, all classes are themselves instances of other classes.
The class of the class of an object is termed the {\bit metaclass\/} of that
object. Less formally, we will also use the term {\bit metaclass\/} to
refer to a class that has instances that are themselves classes.
The metaclass determines the form of inheritance used by its classes and
the representation of the instances of those classes.
A class can inherit properties directly or indirectly from one or more
other classes. A class that is defined so as to inherit from another
class is said to {\bit include\/} that class. A class that inherits
from a class is said to be a {\bit subclass\/} of that inherited
class. A class from which another class inherits properties is called
a {\bit superclass\/} of the inheriting class. The inheritance
relationship is transitive.
Classes are organized into a {\bit lattice}. There is a mapping from
the Common Lisp type lattice into the Common Lisp Object System class
lattice. All of the standard Common Lisp types specified in
{\it Common Lisp: The Language\/} by Guy L. Steele Jr. except {\bf atom}
and {\bf common} have a corresponding class.
The \OS\ includes a set of standard objects. We use the term
{\bit standard object\/} to refer to any object whose metaclass is
{\bf class}. The class {\bf object} specifies the default behavior of the
set of all objects whose metaclass is {\bf class}. In other words,
all standard objects inherit (directly or indirectly) from the class
{\bf object}.
The \OS\ also defines a set of standard classes. A {\bit standard
class\/} is any class that is an instance of the class {\bf class}.
The class {\bf class} is itself of class {\bf class}. It is therefore
both a standard class and a standard object. The class {\bf object}
is also a standard class since it is also an instance of the class
{\bf class}. As a standard object, the class {\bf class} is a
subclass of the class {\bf object}.
\Vskip 1pc!
\boxfig
{\bf\tabskip 0pt plus 1fil
\halign to \hsize{\hfil\cr
array&hashtable&sequence\cr
atom*&integer&short-float\cr
bignum&keyword&simple-array\cr
bit&list&simple-bit-vector\cr
bit-vector&long-float&simple-string\cr
character&nil&simple-vector\cr
common*&null&single-float\cr
compiled-function&number&standard-char\cr
complex&package&stream\cr
cons&pathname&string\cr
double-float&random-state&string-char\cr
fixnum&ratio&symbol\cr
float&rational&t\cr
function&readtable&vector\cr
}}
\caption{Standard Common Lisp types. All these types except atom and common have\break
a corresponding class.}
\endfig
\beginsubSection{Defining Classes}
Classes with metaclass {\bf class} (standard classes)
are defined with the macro {\bf defclass}.
The use and definition of classes with other metaclasses %are
will be
discussed in the chapter ``Meta-Object Protocol.''
The syntax for {\bf defclass} is given in Figure~1-3.
The new class created by {\bf defclass} is a subclass of all the
classes specified in the {\it includes\/} list of the {\bf defclass}
form. A class that is defined in this way is the most specific
element of a sublattice from which descriptions are inherited. The
order of the classes in the {\it includes\/} list determines a local
precedence for classes and for the selection of methods. The
transitive closure of all the {\it includes\/} specifies all the
classes that this class inherits from. An ordering of this list for
purposes of precedence is called the {\bit class precedence list}.
The class precedence list for a standard class is computed as follows:
[To be spec'd.]
%1. A list is created, starting with the given class, of all the classes
%encountered in a depth-first traversal of
%the classes in the {\it includes\/} list of that class. The classes in
%the {\it includes\/} list are processed in left-to-right order (the order
%of local precedence).
%
%2. If more than one occurrence of a class appears in the list that
%results from step 1, only the last occurrence of that class is kept.
%
%3. It is verified that the list that results from step 2 preserves the
%local precedence indicated in the {\it includes\/} list of each class
%encountered. If any such local precedence is violated, an error is
%signalled.
\endsubSection
\vfill\eject
\beginsubSection{Accessing Slots}
Slots can be accessed in two ways: by use of the accessors defined in
the {\bf defclass} form and by use of the primitive function
{\bf slot-value}.
The function {\bf slot-value} can be used with any of the slot names
specified in the {\bf defclass} form to access a specific slot in an object
of the given class. If the object has no such slot, an error is
signalled.
The automatically-generated accessors specified in the {\bf defclass} form
are implemented in terms of {\bf slot-value}.
\endsubSection
\endSection%{Objects and Classes}
\beginSection{Generic Functions}
A {\bit generic function\/} is a function object, which, when it is invoked,
is able to designate one out of a set of operations, depending on the
classes of its arguments. The generic function is said to
{\bit discriminate\/} on the classes of its arguments.
[The following is under discussion:
A generic function is a first-class object in the \CLOS.
It can be used as an argument to {\bf funcall} or {\bf apply} and
stored in the symbol-function cell of a symbol.]
[The following is under discussion: A generic function is created
using the function {\bf make-generic} or the
macro {\bf defgeneric}. The macro {\bf defgeneric} stores the generic function
in a specified symbol-function cell.]
The operations that are provided by a generic function are defined by
the methods associated with it.
A {\bit method\/} is a function object. It consists of two
parts: a set of argument
specifiers that is used to determine when it is applicable and a method
function.
%Methods are first-class objects in the \CLOS.
A method can be used as an argument to {\bf funcall} or {\bf apply} and
stored in the symbol-function cell of a symbol.
A method can be defined and associated
with a generic function by using {\bf defmethod} or {\bf add-method}.
[An issue under discussion is whether a generic function must be defined
before any methods can be added to it.]
When a generic function is invoked, the arguments specifiers of its
associated methods are used to determine which method function is
invoked.
An {\bit argument specifier} is the name of a class or an
individual.
The class of each of the arguments passed to the generic function
is determined and the classes of the arguments are then
compared with the
argument specifiers of each of the methods associated with the generic
function. The method function of the method with the most specific
set of argument specifiers that are identical to or more general than
the classes of the arguments is invoked. The order in which differences
between the classes of the arguments and the arguments specifiers are
considered is defined by the
{\bit argument precedence order\/} for the generic function. The relative
specificity of argument specifiers is determined by the class lattice.
%The {\bf class precedence list} is used to determine
%which specifier is more specific.
Any individual is always more specific than any class. There
is a class named {\bf t} that is more general than any other class. When every
argument specifier in the set of argument specifiers for a method is either
unspecified or {\bf t}, the method function for that method is called the
{\bit default method function\/} of the generic function.
%The precise definition for determining which method of a generic
%function to invoke will be given in section XXX.
\endsubSection
\endSection%{Generic Functions}
\beginSection{Method Combination}
[To be written.]
We are currently working to integrate the programmatic ({\bf
run-super}) and declarative ({\bf define-method-combination}) method
combination techniques. The references to method combination throughout
this document will be further specified in a future draft.
%Methods can be combined by means of the {\bf run-super} construct.
%The {\bf run-super} construct allows a method to specialize a ``super''
%method.
\endSection%{Method Combination}
\beginSection{Metaclasses}
The {\bit metaclass\/} of an object is the class of its class. The metaclass
determines the form of inheritance used by its classes and
the representation of the instances of its classes. The metaclass mechanism
can be used to provide particular forms of optimization or to tailor
the \OS\ for particular uses (such as the implementation of other
object languages---like Flavors, Smalltalk-80, and Loops).
Any new metaclass must define the structure of its instances, how their storage
is allocated, how their slots are accessed, and how slots and methods are
inherited. The protocol for defining
metaclasses will be discussed in the chapter ``Meta-Object Protocol.''
\beginsubSection{Standard Metaclasses}
The \OS\ defines a number of {\bit standard metaclasses}. These include
the following:
{\bf standard-type-class}, {\bf structure-class}, and {\bf class}.
The class {\bf standard-type-class} is a superclass of all the classes
that correspond to the standard Common Lisp types specified in
{\it Common Lisp: The Language\/} by Guy L. Steele Jr. except {\bf atom} and
{\bf common}. These types are listed in Figure~1-1.
This metaclass allows the special kind of class
inheritance rules that are needed to handle the classes that
correspond to the standard Common Lisp types.
It is not possible to make an instance
of a class whose class is {\bf standard-type-class} using the function
{\bf make-instance}.
%It is possible to define methods for built-in classes.
The class {\bf structure-class} is a subclass of {\bf standard-type-class}.
All classes defined by means of {\bf defstruct} are instances or
{\bf structure-class} or a subclass of {\bf structure-class}.
%The use of {\bf defstruct} implicitly defines a new class which is an
%instance of {\bf structure-class}.
%Instances of {\bf primitive-lisp-type-class} are classes that correspond
%to the basic Common Lisp types.
%While all classes that correspond to the types
%listed in Figure~1-1 must be instances of either {\bf structure-class}
%or {\bf primitive-lisp-type-class}, no implementation is {\it required\/} to
%have any class that is an instance of {\bf primitive-lisp-type-class}.
\endsubSection
\beginsubSection{Integrating Types and Classes}
The \OS\ maps the Common Lisp type space into the space
of classes.
Figure~1-2 displays part of the lattice of classes that are instances of
a subclass of {\bf standard-type-class}.
Creating a type by means of {\bf defstruct} also creates a class in
this lattice. Such a class is an instance of {\bf structure-class}
and an immediate subclass of the class that
corresponds to the type given as its
{\bf :includes} argument. If no such type was specified, it
is an immediate subclass of the class {\bf t}.
The following precedence relations hold among classes:
{\bf list} has precedence over {\bf symbol} (for {\bf nil});
{\bf array} has precedence over {\bf sequence} (for vectors);
{\bf vector} has precedence over {\bf simple-array} (for simple-vectors);
{\bf bit-vector} has precedence over {\bf simple-array} (for simple-bit-vectors);
and {\bf string} has precedence over {\bf simple-array} (for simple-strings).
\eject
The classes {\bf number}, {\bf integer}, {\bf rational}, {\bf float},
{\bf list}, and {\bf sequence} are {\bit abstract classes}, that is,
they can never be directly instantiated. The function {\bf class-of}
will never return one of these classes.
\endsubSection%{Integrating Types and Classes}
\eject
\beginsubSection{Lattice of classes that are instances of standard-type-class}
\fig{
\def\IgnoreLineBreaks{\catcode'15=9 \catcode'12=9}
\def\IgnoreWhiteSpace{\catcode'11=9 \catcode'40=9 \IgnoreLineBreaks}
\def\DontIgnoreWhiteSpace{\catcode'12=\active\catcode'15=5\catcode'11=10\catcode'40=10}
\font \pipefont= circlew10
\font \foofont = cmr10 at 1sp
\IgnoreWhiteSpace
\let \adv=\advance
\def\he{height}
\def\wi{width}
\def\de{depth}
\newdimen \stroke
\stroke= \fontdimen8\pipefont % thickness of line in circles
\newdimen \radius \radius=6pt % radius of circles
\newdimen\irad \irad=\radius\advance\irad by -.5\stroke
\newdimen\orad \orad=\radius\advance\irad by .5\stroke
\newbox\BStrutbox
\setbox\BStrutbox\hbox{\vrule\wi0pt\he8.5pt\de8.5pt}
\def\BoxStrut{\unhcopy\BStrutbox}
% Arrows
\newdimen\ArrowShift
\ArrowShift=\fontdimen22\tensy
\advance\ArrowShift by -0.5\stroke
\def\StrikeOut #1
{ \setbox0\hbox{#1}
\hbox to 1\wd0
{ \vrule \he\stroke\de0pt\wi\wd0
\hskip-\wd0
\unhbox0
}
}
\def\LeftArrow
{ \hskip 0.5\stroke
\StrikeOut{\lower\ArrowShift\hbox to 10pt{\tensy\char'40\hss}}
}
\def\RightArrow
{ \StrikeOut{\lower\ArrowShift\hbox to 10pt{\hss\tensy\char'41}}
\hskip 0.5\stroke
}
\def\ArrowLine
{ \StrikeOut{\hskip 10pt\hskip 0.5\stroke}
}
\def\LeftToRight
{ \let\RightSideArrow=\ArrowLine
\let\LeftSideArrow=\RightArrow
}
\def\RightToLeft
{ \let\LeftSideArrow=\ArrowLine
\let\RightSideArrow=\LeftArrow
}
\def\NoArrows
{ \let\LeftSideArrow=\ArrowLine
\let\RightSideArrow=\ArrowLine
}
% boxes around tokens
\let\NonterminalFont=\tenrm
\newbox\TStrutbox
\setbox0\hbox{\NonterminalFont{Bg}}
\setbox\TStrutbox\hbox{\vrule\wi0pt\he\ht0\de\dp0}
\def\TextStrut{\unhcopy\TStrutbox}
\def\HorzLine{\hrule \he \stroke \de 0pt}
\def\HFil{\leaders\HorzLine\hfil}
\def\HFill{\leaders\HorzLine\hfill}
\def\Nonterminal#1
{\setbox1\vbox to 0pt{
\vss
\hbox{\TextStrut\NonterminalFont\space#1\space\hskip-\stroke}
\vss}
\hbox{
\BoxStrut
\LeftSideArrow
\lower\irad\vbox{
\TopSquare
\copy1
\BotSquare}
\RightSideArrow}
}
\def\TopSquare
{ \hbox{
\vrule\he\stroke\de\irad\wi\stroke
\vrule\he\stroke\de0pt\wi\wd1
\vrule\he\stroke\de\irad\wi\stroke}
}
\def\BotSquare
{ \hbox{
\vrule\he\orad\de0pt\wi\stroke
\vrule\he\stroke\de0pt\wi\wd1
\vrule\he\orad\de0pt\wi\stroke}
}
\def\\#1{\Nonterminal{#1}\HFil}
\def\last#1{{\def\RightSideArrow{}\Nonterminal{#1}}}
% piping
\def\foo{\rlap{\foofont\char'40}}
\def\foo{}
\def\FulVert{\vrule \wi\stroke\foo\hskip-\stroke}
\def\TopVert{\vrule\de-\irad \wi\stroke\foo\hskip-\stroke}
\def\BotVert{\vrule\he-\orad \wi\stroke\foo\hskip-\stroke}
\def\Center#1,#2.
{\hskip\radius\foo#1\lower.5\stroke\hbox{\pipefont#2}\hskip\radius}
\def\ru{\char'10\hskip -2\radius}
\def\rd{\char'11\hskip -2\radius}
\def\ld{\char'12\hskip -2\radius}
\def\lu{\char'13\hskip -2\radius}
\def\thru{\hskip-\radius\vrule\he\stroke\de0pt\wi2\radius\hskip\radius\hskip-2\radius}
\def\Center#1,#2.
{\foo\hskip\radius#1{\pipefont#2\unskip}\hskip-\radius}
\def\LT{\Center\BotVert,\lu.}
\def\LU{\Center\FulVert,\lu.}
\def\LL{\Center\FulVert,\ld.}
\def\LB{\Center\TopVert,\ld.}
\def\LMid{\Center\TopVert\BotVert,\rd\ru\thru.}
\def\LMU{\Center\TopVert,\rd\thru.}
\def\LML{\Center\BotVert,\ru\thru.}
\def\LFD{\Center\FulVert,\ru\thru.}
\def\LS{\Center\TopVert\BotVert,\rd\ru.}
\def\RT{\Center\BotVert,\ru.}
\def\RU{\Center\FulVert,\ru.}
\def\RL{\Center\FulVert,\rd.}
\def\RB{\Center\TopVert,\rd.}
\def\RMid{\Center\TopVert\BotVert,\ld\lu\thru.}
\def\RMU{\Center\TopVert,\ld\thru.}
\def\RML{\Center\BotVert,\lu\thru.}
\def\Cross{\Center\FulVert,\thru.}
\def\LR{\Center,\thru.}
\def\TB{\Center\FulVert,.}
% ShiftBox
\newbox\x
\newbox\y
\newbox\tempy
\newbox\z
\newbox\tempz
\def\ShiftBox#1{
\savemod
\saverulebox
\setbox\x
\vbox{ \everycr{\noalign{{\modifyrulebox\global\setbox\z\hbox{}}}}
\halign{&\setbox\x\hbox{##}
\global \setbox\z\hbox{\unhbox\z\vrule\he\ht\x\de\dp\x\wi0pt}
\unhbox\x
\cr
#1}}%
\lower\ht\y\box\x\HFil
\restoremod
\restorerulebox
}
\def\saverulebox{
\setbox\tempy\box\y
\global \setbox\y\vbox{}
\setbox\tempz\box\z
\global \setbox\z\hbox{}
}
\def\restorerulebox{
\global \setbox\y\box\tempy
\global \setbox\z\box\tempz
}
\def\topmod{}
\def\thisrow{\global\let\modifyrulebox\firstmod}
\def\firstmod{
\global\setbox\y\vbox{\hrule\he0pt\wi0pt\de\dp\z}
\global\let\modifyrulebox\latermod
}
\def\latermod{
\global\setbox\y\vbox{\unvbox\y\hrule\he\ht\z\de\dp\z\wi0pt}
}
\def\savemod{
\let\tempmod\modifyrulebox
\global \let\modifyrulebox\topmod
}
\def\restoremod{
\global\let\modifyrulebox\tempmod
}
\DontIgnoreWhiteSpace
{\baselineskip0pt
\lineskip0pt
\LeftToRight
\IgnoreWhiteSpace
\def\ms{\os\os\os\os}
\def\os{\omit\span}
\hbox{
\\{NIL}
\ShiftBox{
\ms\LT\\{bit}&\RT\cr
\ms\ShiftBox{
\ShiftBox{
\ShiftBox{
\LU\\{fixnum}&\RT\cr
\LU\\{bignum}&\RMU\thisrow\cr
}\\{integer}&\RML\thisrow\cr
\LU\\{ratio}&\RB\cr
}\\{rational}&\RT\cr
\ShiftBox{
\LU\\{short-float}&\RT\cr
\LU\\{single-float}&\RMid\thisrow\cr
\LU\\{double-float}&\RL\cr
\LU\\{long-float}&\RB\cr
}\\{float}&\RMid\thisrow\cr
\LU\\{complex}&\RB\cr
}\\{number}&\RU\cr
\ms\LU\\{standard-char}\\{string-char}\\{character}&\RU\cr
\LU\\{keyword}&\os\os\os\RML\\{symbol}&\RU\cr
\LU\\{null}&\os\os\os\LS&\TB\cr
\LMid\\{cons}&\os\os\RMU\\{list}&\RML\\{sequence}&\RMid\thisrow\cr
\os\LL\\{simple-vector}&\LML\HFil&\RML\\{vector}&\LS&\TB\cr
\os\LL\\{simple-bit-vector}&\LFD\\{bit-vector}&\RL&\TB&\TB\cr
\os\LL\\{simple-string}&\LFD\\{string}&\RB&\TB&\TB\cr
\os\TB&\os\LB\HFil\\{simple-array}&\RMU\\{array}&\RL\cr
\ms\LL\\{stream}&\RL\cr
\ms\LL\\{hash-table}&\RL\cr
\ms\LL\\{readtable}&\RL\cr
\ms\LL\\{package}&\RL\cr
\ms\LL\\{pathname}&\RL\cr
\ms\LL\\{function}&\RL\cr
\ms\LL\\{compiled-function}&\RL\cr
\ms\LB\\{random-state}&\RB\cr
}
\last{T}}}
\hbox{}
}\caption{This figure shows all required subclass relationships among the classes that\break
are instances of
standard-type-class, with the exception of classes defined by means of\break
defstruct. Implementations may choose to impose additional ones.}
\endfig
\endSection
%\beginSection{Meta-Objects}
%Includes objects for classes, objects for methods, objects for generic functions.
%Use: efficiency in implementation; experimentation.
%Allows for variations in the representation of objects, the syntax of
%methods, the combination of methods.
%Can be used to provide tuning and optimization for a particular application.
%\endSection
\endChapter
\bye